package com.laity.forkjoin;

import java.util.concurrent.RecursiveTask;

import static java.lang.Long.sum;

/**
 * @author: Laity
 * @Project: JavaLaity
 * @Package: com.laity.forkjoin.ForkJoinDemo
 * @Date: 2023年12月04日 10:31
 * @Description: 基于ForkJoin框架的求和计算
 * 如何使用ForkJoin框架进行计算
 * 1. 继承RecursiveTask
 * 2. 重写compute方法
 * 3. 调用ForkJoinPool.invoke()方法
 * 4. 调用ForkJoinPool.invokeAll()方法
 * 5. 调用ForkJoinPool.invokeAny()方法
 * 6. 调用ForkJoinPool.submit()方法
 * - 通过调用ForkJoinPool来执行任务
 * - 计算任务：调用ForkJoinPool.execute()方法
 */

public class ForkJoinDemo extends RecursiveTask<Long> {

    private static Long start; // 1
    private static Long end;   // 19_0000_0000

    // 临时变量
    private static Long temp = 100000L;

    public ForkJoinDemo(Long start, Long end) {
        ForkJoinDemo.start = start;
        ForkJoinDemo.end = end;
    }

    public static void main(String[] args) {

    }

    public void test() {
        // 1. 继承RecursiveTask
        ForkJoinDemo forkJoinDemo = new ForkJoinDemo(start, end);
        // 2. 重写compute方法
        forkJoinDemo.fork();
        // 3. 调用ForkJoinPool.invoke()方法
        // forkJoinDemo.invoke();
        // 4. 调用ForkJoinPool.invokeAll()方法
        // forkJoinDemo.invokeAll();
        // 5. 调用ForkJoinPool.invokeAny()方法
        // forkJoinDemo.invokeAny();
        // 6. 调用ForkJoinPool.submit()方法
        // forkJoinDemo.submit();
        // 7. 调用ForkJoinPool.execute()方法
        // forkJoinDemo.execute();
    }

    public void ord() {
        // 普通方式
        int sum = 0;
        for (int i = 1; i <= 10_0000_0000; i++) {
            sum += i;
        }
        System.out.println(sum);
    }

    // 计算方法
    @Override
    protected Long compute() {

        if ((Long) (end - start) <= temp) {
            Long sum = 0L;
            for (long i = 1L; i <= end; i++) {
                sum += i;
            }
            System.out.println(sum);
            return sum;
        } else {
            // 使用ForkJoin框架
            // 递归
            long mid = (start + end) / 2; // 中间值
            // 拆分任务
            ForkJoinDemo left = new ForkJoinDemo(start, mid);
            left.fork(); // 拆分任务，把任务压入线程队列(双端队列)
            ForkJoinDemo right = new ForkJoinDemo(mid + 1, end);
            right.fork();
            // 等待子任务
            return sum(left.join(), right.join());
        }
    }
    /*
    人生自信两百年，会当击水三千里
     */
}
